'''
Created on 2009-10-22

@author: summit
'''
import wx
import  wx.gizmos   as  gizmos
#from vtk.util.vtkImageExportToArray  import *

try:
    from agw import foldpanelbar as fpb
except ImportError: # if it's not there locally, try the wxPython lib.
    import wx.lib.agw.foldpanelbar as fpb

try:
    from agw import aquabutton as AB
except ImportError: # if it's not there locally, try the wxPython lib.
    import wx.lib.agw.aquabutton as AB

try:
    from agw import balloontip as BT
except ImportError: # if it's not there locally, try the wxPython lib.
    import wx.lib.agw.balloontip as BT

from jolly.wxext.AbstractModel import *
import vtk.util.numpy_support as VN
import numpy

class MeasureModel(AbstractModel):
    def __init__(self, datamanager=None):
        
        AbstractModel.__init__(self)
        
        self._datamanager = datamanager
        self._currentname = ""
        self._lower = 0
        self._upper = 255
        self._volume = None
        self._spacing = [1.0, 1.0, 1.0]
        
    def GetAllNameInManager(self):
        return self._datamanager.GetAllNameInManager()
    
    def SetCurrentName(self, arg):
        self._currentname = arg
        self.update()
    
    def GetCurrentName(self):
        return self._currentname
    
    def GetCurrentSpacing(self):
        if self._currentname<>"":
            metadata =  self._datamanager.GetMetaDataSetFromName(self._currentname)
            if metadata:
                return metadata.GetImageData().GetSpacing()
            else:
                return None
        return None
    
    def GetCurrentOrigin(self):
        if self._currentname<>"":
            metadata =  self._datamanager.GetMetaDataSetFromName(self._currentname)
            if metadata:
                return metadata.GetImageData().GetOrigin()
            else:
                return None
        return None
    
    def SetVolume(self, arg):
        self._volume = float(arg)
    
    def GetVolume(self):
        return self._volume
    
    def SetLower(self, arg):
        try:
            self._lower = float(arg)
            self.update()
        except:
            pass
    
    def GetLower(self):
        return self._lower
    
    def SetUpper(self, arg):
        try:
            self._upper = float(arg)
            self.update()
        except:
            pass
    
    def GetUpper(self):
        return self._upper
    
    def SetSpacingX(self, arg):
        try:
            self._spacing[0]=float(arg)
            
        except:
            pass
    
    def SetSpacingY(self, arg):
        try:
            self._spacing[1]=float(arg)
            
        except:
            pass
    
    def SetSpacingZ(self, arg):
        try:
            self._spacing[2]=float(arg)
           
        except:
            pass
    
    def SetSpacing(self, arg):
        try:
            self._spacing = arg
           
        except:
            pass
        
    def GetSpacing(self):
        return self._spacing
    
        
    def Update(self):
        if self._currentname<>"":
            metadata =  self._datamanager.GetMetaDataSetFromName(self._currentname)
            if metadata:
                imarray = VN.vtk_to_numpy(metadata.GetImageData().GetPointData().GetScalars())
                xmin, xmax, ymin, ymax, zmin, zmax = metadata.GetImageData().GetWholeExtent()  
                imarray = imarray.reshape(zmax-zmin+1, ymax+1, xmax+1)
                
                # compute the volume
                self._volume = numpy.sum( numpy.logical_and(imarray>=self._lower, imarray<=self._upper))
                
                if self._spacing is None:
                    self._spacing  = metadata.GetImageData().GetSpacing()
                
                self._volume = self._spacing[0]*self._spacing[1]*self._spacing[2]*float(self._volume)
               
                self.update()
                
               

        
class MeasurePanel(wx.Panel):
    def __init__(self, parent, id, model=None, pos=wx.DefaultPosition, size=wx.DefaultSize,
                 style=wx.NO_BORDER | wx.TAB_TRAVERSAL):
        '''
        '''
        wx.Panel.__init__(self, parent, id, pos, size, style)
        
        self.model = model
        self.spacing = None
        self.origin = None
        
        if self.model:
            self.model.addListener(self.UpdateControl)
        self.CreateControls()
        self.UpdateControl(self.model)
        self.GetSizer().Fit(self)
        self.GetSizer().SetSizeHints(self)
        self.GetSizer().Layout()
    
        self.Bind(fpb.EVT_CAPTIONBAR, self.OnPressCaption)
        
    
    def OnPressCaption(self, event):
        event.Skip()
    
    def CreateControls(self):
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        
        subpanel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize,
                            wx.NO_BORDER | wx.TAB_TRAVERSAL)
        sizer.Add(subpanel, 1, wx.GROW | wx.ADJUST_MINSIZE, 5)
        
        
        
        subsizer = wx.GridBagSizer(5, 5)
        subpanel.SetSizer(subsizer)
        
        # row
        self.elb = gizmos.EditableListBox(
                    subpanel, -1, "List of MetaDataSet"
                    )
        self.elblist = self.elb.GetListCtrl()
        print self.elblist
        subsizer.Add(self.elb, (0,0), (1,7),wx.EXPAND)
        self.elb.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelectedChanged, self.elblist)
        
        #row
        subsizer.Add(wx.StaticText(subpanel,-1, "Spacing x:"), (1,0), flag=wx.ALIGN_RIGHT | wx.ALL)
        self.sx = wx.TextCtrl(subpanel,-1, "0.0000")
        subsizer.Add(self.sx , (1,1), flag=wx.ALIGN_CENTER | wx.ALL)
        subsizer.Add(wx.StaticText(subpanel,-1, "Spacing y:"), (1,2), flag=wx.ALIGN_RIGHT | wx.ALL)
        self.sy = wx.TextCtrl(subpanel,-1, "0.0000")
        subsizer.Add(self.sy , (1,3), flag=wx.ALIGN_CENTER | wx.ALL)
        subsizer.Add(wx.StaticText(subpanel,-1, "Spacing z:"), (1,4), flag=wx.ALIGN_RIGHT | wx.ALL)
        self.sz = wx.TextCtrl(subpanel,-1, "0.0000")
        subsizer.Add(self.sz , (1,5), flag=wx.ALIGN_CENTER | wx.ALL)
        self.Bind(wx.EVT_TEXT, self.OnChangedSpacingX, self.sx)
        self.Bind(wx.EVT_TEXT, self.OnChangedSpacingY, self.sy)
        self.Bind(wx.EVT_TEXT, self.OnChangedSpacingZ, self.sz)
        
        #row
        subsizer.Add(wx.StaticText(subpanel,-1, "Origin x:"), (2,0), flag=wx.ALIGN_RIGHT | wx.ALL)
        self.ox = wx.TextCtrl(subpanel,-1, "0.0000")
        subsizer.Add(self.ox , (2,1), flag=wx.ALIGN_CENTER | wx.ALL)
        subsizer.Add(wx.StaticText(subpanel,-1, "Origin y:"), (2,2), flag=wx.ALIGN_RIGHT | wx.ALL)
        self.oy = wx.TextCtrl(subpanel,-1, "0.0000")
        subsizer.Add(self.oy , (2,3), flag=wx.ALIGN_CENTER | wx.ALL)
        subsizer.Add(wx.StaticText(subpanel,-1, "Origin z:"), (2,4), flag=wx.ALIGN_RIGHT | wx.ALL)
        self.oz = wx.TextCtrl(subpanel,-1, "0.0000")
        subsizer.Add(self.oz , (2,5), flag=wx.ALIGN_CENTER | wx.ALL)
        
        #row
        subsizer.Add(wx.StaticText(subpanel,-1, "Lower pixel:"), (3,0), flag=wx.ALIGN_RIGHT | wx.ALL)
        self.low = wx.TextCtrl(subpanel,-1, "0")
        subsizer.Add(self.low , (3,1), flag=wx.ALIGN_CENTER | wx.ALL)
        subsizer.Add(wx.StaticText(subpanel,-1, "Upper pixel:"), (3,4), flag=wx.ALIGN_RIGHT | wx.ALL)
        self.upper = wx.TextCtrl(subpanel,-1, "255")
        subsizer.Add(self.upper , (3,5), flag=wx.ALIGN_CENTER | wx.ALL)
        self.Bind(wx.EVT_TEXT, self.OnChangedLower, self.low)
        self.Bind(wx.EVT_TEXT, self.OnChangedUpper, self.upper)
        
        #row
        self.vr = wx.StaticText(subpanel,-1, "")
        subsizer.Add(self.vr , (4,0),(1,7),  flag=wx.ALIGN_CENTER | wx.ALL)
        
        # row
        self.btn = AB.AquaButton(subpanel, -1, None, "stereometry")
        self.btn.SetHoverColour((0.8900*255, 0.5100*255, 0.0900*255, 255))
        self.btn.SetBackgroundColour((0.0000*255, 0.7490*255, 1.0000*255, 255))
        self.btn.SetForegroundColour((0,0,0,255))
        subsizer.Add(self.btn, (5,0), (1,7),wx.EXPAND)
        self.Bind(wx.EVT_BUTTON, self.OnStereometry, self.btn)
        
        tipballoon = BT.BalloonTip(topicon=None, toptitle="Button Help",
                                       message="calculate the vomule of imagedata", shape=BT.BT_ROUNDED,
                                       tipstyle=BT.BT_LEAVE)
        tipballoon.SetTarget(self.btn)
        tipballoon.SetStartDelay(100)
        
        subsizer.AddGrowableCol(6)
        subsizer.AddGrowableRow(6)
        
    
    
    def UpdateControl(self, model):    
        if self.model<>None:
            if self.elb.GetStrings()<> self.model.GetAllNameInManager():
                self.elb.SetStrings(self.model.GetAllNameInManager())
            
            
            self.spacing = self.model.GetSpacing()
            
            self.sx.SetValue("%f"%(self.spacing[0]))
            self.sy.SetValue("%f"%(self.spacing[1]))
            self.sz.SetValue("%f"%(self.spacing[2]))
            
            if self.origin is None:
                self.origin = self.model.GetCurrentOrigin()
            if self.origin is None:
                self.ox.SetValue("%f"%(1.0))
                self.oy.SetValue("%f"%(1.0))
                self.oz.SetValue("%f"%(1.0))
            else:
                self.ox.SetValue(str(self.origin[0]))
                self.oy.SetValue(str(self.origin[1]))
                self.oz.SetValue(str(self.origin[2]))
            
            print "Volume:", self.model.GetVolume()
            if self.model.GetVolume()<>None:
                self.vr.SetLabel( "The %s's volume is %s mm^3" %(self.model.GetCurrentName(), 
                                                                 self.model.GetVolume()) )
            
    
    def OnSelectedChanged(self, event):
        self.model.SetCurrentName(event.GetText())
    
    def OnChangedLower(self, event):
        self.model.SetLower(event.GetString())
    
    def OnChangedUpper(self, event):
        self.model.SetUpper(event.GetString())
    
    def OnChangedSpacingX(self, event):
        self.model.SetSpacingX(event.GetString())
    
    def OnChangedSpacingY(self, event):
        self.model.SetSpacingY(event.GetString())
    
    def OnChangedSpacingZ(self, event):
        self.model.SetSpacingZ(event.GetString())
    
    def OnStereometry(self, event):
        self.model.Update()
if __name__ =="__main__":
    import numpy
    
   